/*
 * mymy.cpp
 *
 *  Created on: 2019-12-4
 *      Author: root
 */

#include<stdio.h>
#include "mymy.h"
#include "share_type.h"
#define container_of(ptr, type, member) ({const typeof( ((type *)0)->member ) *__mptr = (ptr);		(type *)( (char *)__mptr - offsetof(type,member) );})
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
/*
ptr是指向结构体成员的指针
type是结构体的类型，例如struct abc
member是成员的变量名
*/
/*
1、typeof( ((type *)0)->member )：取得成员的类型
2、const typeof( ((type *)0)->member ) *__mptr = (ptr); ：定义指向成员类型的指针变量__mptr，并将第一个参数（指向成员的指针）赋值给__mptr
3、offsetof(type,member) : 计算结构体中成员变量相对于结构体指针的偏移量
4、(TYPE *)0)->MEMBER：起始地址为0的结构体中成员变量的地址，也就是成员的偏移值
PS：这个实现最巧妙的地方在于“(type *)0”的应用，将地址0强行转换成指向某个类型的指针
*/
//struct student{
//	char name[20];
//	char sex;
//}stu = {"xiaobo",'m'};


student1 stu = {"xiaobo",'m'};
int xxxxx()
{

	student1 *ptr;

	ptr=(student1 *)0;
//	struct sudent *ptr;
//	ptr = (struct student *)0;
	printf("stu的起始地址：%p/n",&stu);
	printf("stu.sex的起始地址：%p/n",&(stu.sex));
	printf("stu.sex的起始地址：%p/n",ptr);
	//printf("stu.sex的起始地址：%p/n",(*ptr)->sex);
	student1 *stu_ptr;
	int offset;
	/*
	const typeof( ((type *)0)->member ) *__mptr = (ptr);
	首先定义一个 _mptr指针， 类型为struct student结构体中sex成员的类型
	typeof 为获取（（（struct student＊）0）->sex)的类型，此处此类型为char
	*/
	const typeof(((student1 *)0)->sex) *_mptr = &stu.sex;
	/*
	（（struct student＊）0）为 把 0地址 强制转化为指向student结构体类型的指针
	该指针从地址 0 开始的 21个字节用来存放name 与 sex（char name〔20〕与 char sex共21字节）
	sex存放在第20个字节出（从0字节开始）
	&((struct student *)0)->sex 取出sex地址(此处即为20) 并强制转化为整形从而得出sex相对于0
	的偏移量
	*/

	offset = (int)&(((student1 *)0)->sex);//偏移量
	stu_ptr = (student1 *)((char*)_mptr - offset);
	printf("offsetof stu.sex = %d/n",offset);
	printf("stu_ptr->name:%s/tstu_ptr->sex:%c/n",stu_ptr->name,stu_ptr->sex);
	/*利用linux 中的宏定义*/
	student1 *stu_ptr2;
	stu_ptr2 = container_of(&stu.sex,student1,sex);
	printf("stu_ptr2->name:%s/tstu_ptr2->sex:%c/n",stu_ptr2->name,stu_ptr2->sex);

	return 0;
}
/*
输出结果：
	stu的起始地址：0x804a014
	stu.sex的起始地址：0x804a028
	stu.sex的起始地址：(nil)
	offsetof stu.sex = 20
	stu_ptr->name:xiaobo	stu_ptr->sex:m
	stu_ptr2->name:xiaobo	stu_ptr2->sex:m
	巧妙之处是利用(type *)0，将地址0强行转换成指向某个类型的指针，并利用其中某个成员的地址，计算出其相对于0的偏移量从而得出该结构体的指针 即其地址
	下面再给出这个巧妙之处的一个例子。
*/
